1. Field of the Invention
This invention relates to computer memory management. More particularly, it relates to application program access to expanded memory via the Lotus/Intel/Microsoft Expanded Memory Specification on computers having extended memory and memory paging capabilities.
2. Description of the Related Art
Many popular personal computers (PC's) are based on Intel microprocessors (Intel Corporation, 3065 Bowers Ave. Santa Clara, Calif. 95051). These include the model 8080, introduced in 1974, the 8088 which is used in the Compaq Portable and the IBM-PC, the 8086 used in the Compaq Deskpro, the 80286 used in both the Compaq Deskpro 286 and the IBM-PC AT, and the 80386 processor of the Compaq Deskpro 386. These microprocessors have been designed for upward compatibility--programs written for the 8088 and/or the 8086 can be run on computers having 80286 or 80386 processors and programs written for the 80286 processor can be run by the 80386.
The amount of physical memory a microprocessor can access depends on the number of address lines that emanate from the chip. Each additional bit doubles the amount of addressable memory.
The Intel 8080 microprocessor has 16 address lines and can therefore access 65536 (2.sup.16) memory locations. By convention, microcomputer memory consists of 8-bit bytes. Thus, the 8080 can access 64 kilobytes (64KB) of memory. On the machine-code level, a program accesses memory with addresses that are stored as values in the internal registers of the microprocessor. Although the 8080 is an 8-bit microprocessor, the instruction pointer (a register used to address machine code) is 16 bits wide. For addressing data, the 8080 employs two 8-bit registers used in conjunction. The resultant 16-bit value directly addresses a location in the 64KB memory space.
As noted above, the Intel 8086 and the 8088 were designed to be upwardly compatible with the 8080 on a source-code level. (Although 8080 machine code itself cannot be executed by an 8086, an 8080 assembly language program can be converted into equivalent 8086 machine code.) Yet, the 8086 and 8088 can address one megabyte of memory, which requires a 20-bit address. For the purposes of this disclosure, the 8088 and the 8086 may be considered functionally equivalent and will henceforth be referred to as "the 8086." Unless explicitly stated otherwise, references to "the 8086" may be taken as applying equally well to the 8088 microprocessor.
Rather than introduce a 20-bit register into the 8086, the 20-bit address is split into two pieces--a 16-bit segment address and a 16-bit offset address. These two pieces are stored in different registers. The microprocessor shifts the segment address 4 bits left (thereby effectively multiplying it by 16) and then adds the offset address. The result is a 20-bit address that can access 1 megabyte of memory. It should be appreciated that various combinations of segment and offset can produce the same physical address.
By convention, a 20-bit address can be shown broken down into its segment and offset parts using the notation 0000:0000, the segment being to the left of the colon and the offset on the right. For example, a 20-bit address written as FFE6E in hexadecimal notation could be written as FFE4:002E in segmented notation. Depending upon which segment (or "segment paragraph") is chosen, a single 20-bit address can be expressed in a variety of ways using segmented notation. For example, the physical address 00030 can be accessed by all the following segments and offsets (segment paragraphs and relative offsets): 0000:0030; 0001:0020; 0002:0010; and, 0003:0000.
Each of the four segment registers in the 8086 defines a 64KB block of memory called a "segment." If all the segment registers are kept constant and equal, then the microprocessor can access only 64KB of memory, just like the 8080.
The 80286 and 80386 microprocessors both support and go beyond the segmented addressing scheme of the 8086. When first powered up, they operate in "real mode," which uses segment and offset registers in the same way as the 8086 to access the same one megabyte of memory. Thus the 80286 and 80386 microprocessors are upwardly compatible with the addressing scheme of the 8086 chip.
In addition to real mode operation, the 80286 and 80386 can operate in "protected mode." The difference with protected mode is that the segment register is no longer a real (i.e., physical) address. Instead, the 80286 microprocessor used the upper (most significant) 14 bits of the segment register to look up a 24-bit base address stored in a descriptor table also in memory. The 80286 adds the 16-bit offset address to this base address. The 24 bits allow access to 16 megabytes of memory (2.sup.24) instead of 1 megabyte (2.sup.20).
The on-chip memory management and multitasking abilities of the 80286 and 80386 are also part of protected mode. With protected mode, segment registers define the way that memory is organized between tasks. Each task has its own descriptor table describing the segments for that task, and that (along with the registers) is virtually all that the chip needs to store to switch between tasks. Since physical addresses are stored in the descriptor table rather than in the segment registers, the operating system can move memory around without application programs being affected.
Protected mode is so named because segments belonging to one task are protected from being corrupted by another task. Tasks are organized in privilege levels, and certain machine-code instructions are prohibited to lower privilege levels. In a well-designed protected-mode operating system, a single program can neither crash the whole system nor get itself into an unrecoverable state.
On the 80386 the base address associated with each segment is not limited to 24 bits, as in the 80286. Rather, it is 32 bits wide and thus can be anywhere within the 4 gigabytes (2.sup.32) of addressable memory. If the top 8 bits (eight most significant bits) of the base addresses are set to zero, then the 80386 addressing scheme works just like that of the 80286.
The offset addresses of the 80386 in protected mode are expanded from 16 bits to 32 bits. This overcomes the 64KB segment limit of the 80286 protected mode and allows a 4-gigabyte maximum segment size.
In addition to real mode and protected mode, the 80386 has an additional mode of operation known as virtual 8086 mode which permits the processor to imitate multiple 8086- or 8088-based machines while it is also running in protected mode. As the name implies, the 80386 can mimic a 1-megabyte addressing environment that to existing programs appears to be an 8086. But unlike real mode, more than 1 megabyte is available. The 80386 can actually maintain more than one virtual 8086 environment in memory at the same time. Each of these environments can have its own copy of the operating system and an application program. At the same time, a protected mode operating system and application can be using a different area of memory.
In virtual 8086 mode, the 80386 treats the segment registers the same way as in real mode, where they represent real (i.e., physical) addresses. Thus, existing DOS programs (and DOS itself) can operate in the conventional manner with segment registers and not run into the problems associated with protected mode.
The addresses from multiple virtual 8086 sessions do not collide when they access physical memory because when the 80386 adds the segment and offset registers together, it creates not a physical address, but a linear address. A set of paging tables translates the linear address into a physical address. This physical address may be anywhere in the 4 gigabytes of the 80386 addressable memory.
The paging hardware of the 80386 (described infra and which is not limited to virtual 8086 mode) works with 4K-byte blocks of memory. The pages can be set up so that some memory (for instance, a single ROM BIOS) is used by several virtual 8086 sessions. Virtual 8086 mode solves the problem of allowing programs that write directly to the display memory to be multitasked. The address of the display can be mapped to another location in memory and transferred to the real display during program switching. Alternatively, the operating system can combine display output from several virtual 8086 sessions into a single-windowed real display.
All interrupts and all I/O port accesses initiated by programs in virtual 8086 mode can be trapped by the operating system that has set up these virtual 8086 environments. To correctly handle these I/O port accesses, this operating system would have to have complete knowledge of all hardware that may be directly accessed by more than one virtual 8086 session.
The entire 1 megabyte address space of the 8086 can be thought of as divided into 16 blocks of 64K each. Each of these blocks of memory can be identified by the high-order (most significant) hex digit that all addresses in that block share. Thus, the first 64K of memory can be called the 0 block, since all addresses in that block are 0xxxx (in five-digit absolute address notation) or 0xxx:xxxx (in segmented address notation). Likewise, the second block is the 1-block, since all addresses in that 64K begin with 1. In the 1 megabyte address space, there are 16 blocks of 64K, which may be designated the 0-block through the F-block (in hexadecimal notation).
Many 8086-based personal computers such as the Compaq Portable or the IBM-PC use MS-DOS ("DOS"; Microsoft Corporation, 107000 Northup Way, Bellevue, Wash. 98009) as the operating system. The key working area of their memory is that part used for programs and their data--the area made up of the first ten blocks, the 0-through 9-blocks. This area is often called the user memory area to distinguish it from the rest of the address space, which is, one way or another, at the service of the computer system itself. Thus, the maximum amount of user memory is 640K (all ten blocks installed).
Immediately following the user memory area is a 128K area, consisting of the A- and B-blocks, that is set aside for use by the display screens. The memory that is installed for use by the display screens operates in the same fashion as conventional read/write Random Access Memory ("RAM") used for user memory. Normally, it has one extra feature which helps speed the operation of the computer: there are two circuit pathways into it, so that both programs (being run by the microprocessor) and the display screen can simultaneously work with it, without interfering with each other.
After the display memory area comes three blocks, C through E, which are commonly set aside for some special uses. These blocks are called the "ROM extension area." One use, which gives this section its name, is as a growth area for the last section of memory, the ROM-BIOS which occupies the final F-block. Another use for the ROM extension area is for removable software cartridges. A third use for the ROM extension area is to support "extended memory" discussed infra.
The final part of the 8086 memory address space is the F-block, which is used to hold the computer's built-in ROM-BIOS programs. The ROM-BIOS holds a key set of programs that provide essential support for the whole operation of the computer. These include the power-on self-test and the basic input/output service routines.
FIG. 1 depicts the above-described allocation of memory blocks for an 8086-based computer.
The portion of memory above 1 megabyte which can be addressed by the 80286 and 80386 microprocessors (100000h through FFFFFFh and 100000h through FFFFFFFFh, respectively) is referred to as extended memory. Thus, extended memory is the 15M-byte address space on an 80286 based computer which lies outside the memory DOS can access. This address space is of little use to those application programs that use DOS since DOS does not recognize memory above 640K. The XENIX operating system manages extended memory. Extended memory is sometimes called expansion memory (not to be confused with expanded memory). This is physical memory which is addressed beginning at 1 megabyte and is normally accessed only by protected mode programs.
To take full advantage of extended memory or virtual memory one must have an operating system environment (and accompanying programs) that is designed for those features. Since the 8086 and its mainstream operating system, MS-DOS, were not developed with extended and virtual memory in mind, the potential of these features remains largely untapped.
However, it is still possible for a program to make some use of extended memory. One way to do this is for a program to use some of the services provided by the computer's built-in ROM-BIOS programs. One of these services transfers blocks of data, in whatever size is needed, between the extended memory and conventional memory. An example of a program that uses the BIOS's transfer service to use extended memory is the virtual disk utility called VDISK which has been a part of DOS since version 3.0. When VDISK is activated with the extended memory, it uses the BIOS transfer service to move data into and out of extended memory without VDISK needing to work in protected mode or directly manipulate the extended memory area.
As discussed above, an 8086-based computer is limited to only addressing one megabyte of storage, and only using 640K of that for working programs and data. For some applications, most notably large spreadsheets, this is too little memory. One solution to this problem is bank-switched memory.
Bank-switching allows the computer to actually have more memory than can be directly addressed in the microprocessor's 1MB memory address space. The memory is physically in the computer, but it is not actually assigned any particular place in the microprocessor's address space. Bank-switched memory is inaccessible to application programs until it is switched on.
The circuit boards for this special kind of bank-switched memory allow the addressing of the memory to be turned on and off at will, and moved around at will. For example, a bank-switched memory board might contain eight "banks" of memory, each of them 64K (for a total of 512K). All of these 64K blocks share a single 64K address block in the computer's memory. At any instant, only one of these eight banks can be active, with its data accessible, while the others will be on hold.
The benefit of bank-switching is that it allows more memory to be attached to the computer, memory that is instantly accessible. All that it takes to switch a bank into place is to send a command to the memory circuit board, telling it to change the addressing of the banks. The switch takes place as quickly as an instruction can execute.
Unlike the computer's conventional memory, bank-switched memory requires active management to make sure that the right pieces are available at the right times. As a result of the need for that management, Lotus Development Corporation, Intel Corporation, and Microsoft Corporation collaborated to define a standard way of working with bank-switched memory. This bank-switched approach is called the Lotus/Intel/Microsoft Expanded Memory Specification ("the LIM specification"). Version 3.20 of the LIM specification dated September, 1985, (Part Number 00275-003) is incorporated by reference into this disclosure.
Expanded memory operates in three parts: one piece of hardware (the bank-switched memory board), and two pieces of software (the expanded memory manager--known as the EMM--and the application program that uses the memory). The bank-switched memory board--which can be Intel's "Above Board," AST's "RAMpage!" or any similar memory board--provides anywhere from 64K up to 8 megabytes of memory, subdivided into small 16K pages that can be individually readdressed through bank-switching.
The EMM memory manager program is activated when the computer is first started up, and it lays the groundwork for the expanded memory's operation. A key part of its task is to find an unused area in the computer's memory space into which it can map the bank-switch memory. It requires a full 64K work area, called a page frame. As can be seen from the general memory allocation shown in FIG. 1, the D and E blocks of memory are obviously good candidates for the location of the page frame; however, the EMM can place the page frame in the C block as well. The exact location doesn't matter, as long as it doesn't interfere with any other use of the memory address space. Also, the 64K page frame doesn't have to be placed on a memory block boundary. For example, it can begin at the segment address C400 and extend up through the rest of the C block and into the first 16K of the D block.
Once the EMM has established where its 64K page frame will be located, it divides the frame into four 16K windows. After that, the EMM will supply any application program which adheres to the LIM specification with the service of swapping memory data in and out of the 16K windows.
To use the expanded memory, an application program tells the EMM that it needs to use one or more of the four available windows. The application can request the EMM supervisor to assign memory pages to it, and then to make those pages accessible by bank-switching them into the window area. As the application program needs to work with different 16K pages of data, it asks the EMM to switch different pages into place.
Expanded memory can be used only for a program's data, not for the program code itself. DOS still has to find sufficient room in the conventional memory area to hold large programs, but once those programs are running in conventional memory, they can take advantage of expanded memory to work with more data than can be accommodated in conventional memory. Conventional memory is the memory DOS recognizes; in 8086-, 8088- and 80286-based computers this is memory between 0 and 640K bytes. Because application programs let DOS manage their memory, they can use only conventional memory.
One drawback to expanded memory is that to use it a program must be written to work together with the expanded memory manager, EMM, and it must know how to conveniently work with its data fragmented into 16K pages. Despite this and other limitations, the expanded memory scheme can greatly enhance a computer's ability to work with large amounts of data.
The expanded memory scheme discussed above can be used with any 8086-compatible computer including those based on the 80286 and the 80386. While the 286 and 386 can have their own extended memory that goes beyond the 8086's 1MB limit, they can also use expanded memory within the conventional address space.
Unlike the 8086, 8088, and 80286, the 80386 microprocessor incorporates memory paging hardware. This allows linear addresses (as seen by programs) to be mapped to physical memory addresses. This facility allows the efficient implementation of virtual memory systems. With memory paging support, the operating system can easily allocate contiguous memory to an application simply by mapping a number of noncontiguous physical memory pages into the requested logical program space. This mapping of a program's linear address space into physical memory is shown schematically in FIG. 2.
The mapping of noncontiguous physical memory pages into a requested logical program space is performed by updating the page directory and page tables. An 80386 operating system enables paging by setting the PG (Paging Enabled) bit in Control Register 0 (CR0) with a privileged instruction. When paging is enabled, the processor translates a linear address to a physical address with the aid of page tables. Page tables are the counterparts of segment descriptor tables; as a task's segment descriptor table defines its logical address space, a task's page tables define its linear address space. An 80386's task's page tables are arranged in a two-level hierarchy as shown in FIG. 3. Each task can have its own page table directory. The 80386's CR3 (Page Table Directory Base) system register points to the running task's page table directory; the processor updates CR3 on each task switch, obtaining the new directory address from the new task's Task State Segment (TSS).
A page table directory is one page long and contains entries for up to 1024 page tables. Page tables are also one page long, and the entries in a page table describe 1024 pages. Thus, each page table maps 4 megabytes and a directory can map up to 4 gigabytes, the entire 32-bit physical address space of the 80386.
FIG. 3 shows in functional terms how the 80386 microprocessor translates a linear address to a physical address when paging is enabled. The processor uses the upper 10 bits of the linear address as an index into the directory. The selected directory entry contains the address of a page table. The processor adds the middle 10 bits of the linear address to the page table address to index the page table entry that describes the target page. Adding the lower 12 bits of the linear address to the page address produces the 32-bit physical address.
FIG. 4 shows the basic content of a page table entry. Directory entries are identical, except that the page address field is interpreted as the physical address of a page table, rather than a page.
Tasks can share individual pages or entire page tables. Entries in different page tables that point to the same page are aliases of one another just as descriptors with the same base address are aliases of one another. The 80386's two-level page table structure makes it easier to share pages between tasks by sharing entire page tables. Since the address of a page shared in this way exists in a single page table, the operating system has one page table entry to update when it moves the page.
Using the 80386 memory paging functions, a demand-page operating system can manage memory for multiple virtual-8086 mode machine simulations concurrently with protected mode applications. Memory paging also can be used to allow each 8086 machine simulation to have access to common routines and data, such as a system ROM, by making the physical ROM appear in the memory space of each simulated machine. Actually, only one ROM exists, but each machine sees it at the expected address within its 1MB address space.
FIG. 5 shows how the 80386 paging mechanism enables multiple virtual-8086 machines to be managed. A single copy of the 8086 operating system is made to appear in the address space of both machines. The paging mechanism gives each virtual-8086 task a 1MB linear address space. Read-only areas, such as the 8086 operating system, can reside on shared pages used by all virtual-8086 tasks. Unused pages can be omitted from physical memory.
Inasmuch as addressing is an important feature of the invention, there follows a discussion of the way in which the 80386 microprocessor addresses memory.
The physical address space of most computers is organized as a simple array of bytes. With the development of memory management units (MMU's), computer architectures began to distinguish between the physical address space implemented by the memory hardware and the logical address space seen by a programmer. The MMU translates the logical addresses presented by programs into the physical addresses that go out on the bus. Most architectures view a task's logical address space as consisting of a collection of one of the following:
Bytes: The logical address space consists of an array of bytes with no other structure (this is sometimes called a "flat" or "linear" address space). No MMU translation is required because a logical address is exactly equivalent to a physical address.
Segments: The logical address space consists of a few or many segments, each of which is composed of a variable number of bytes. A logical address is given in two parts, a segment number and an offset into the segment. The MMU translates a logical address into a physical address.
Pages: The logical address space consists of many pages, each of which is composed of a fixed number of bytes. A logical address is a page number plus an offset within the page. The MMU translates a logical address into a physical address.
Paged Segments: The logical address space consists of segments which themselves consist of pages. A logical address is a segment number and an offest. The MMU translates the logical address into a page number and an offset and then translates these into a physical address.
Technically, the 80386 views memory as a collection of segments that are optionally paged. In practice, the 80386 architecture supports operating systems that use any of the four views of memory described above.
FIG. 6 shows the fundamentals of 80386 logical-to-physical address translation. The sequence of operations shown in FIG. 6 is central to both addressing and protection.
The 80386 memory addressing modes yield the 32-bit offset of the target operand. Combined with a segment selector, this offset forms a two-part logical address: the selector identifies the target segment and the offset locates the operand in the segment. In the vast majority of instructions, the selector is specified implicitly as the content of a segment register.
A selector is an index into a segment descriptor table; that is, it is a segment number. Each entry in a segment descriptor table contains the base address of a segment. The processor adds the offset to the segment's base address to produce a 32-bit linear address. If paging is not enabled, the processor considers the linear address to be the physical address and emits it on the address pins.
If paging is enabled, the 80386 translates the linear address into a physical address. It does this with the aid of page tables. A page table is conceptually similar to a descriptor table except that each page table entry contains the physical base address of a 4KB page.
An operating system can provide a task with a single flat address space, a flat address space that is paged, a segmented address space, or a segmented address space that is paged.
The segment is the unit the 80386 provides for defining a task's logical address space; that is, a task's logical address space consists of one or more segments. An instruction refers to a memory operand by a two-part logical address consisting of a segment selector and an offset into the segment. In principle, the 80386 translates the logical address to a linear address by using the selector to look up the segment's descriptor in a segment descriptor table. The descriptor contains the segment's base address in the linear address space; adding the offset produces the operand's linear address. In practice, the logical-to-linear address translation is optimized by implicit selectors and register-based descriptors. As a result, the descriptor table lookup only occurs for instructions that load new selectors into segment registers.
In the second phase of address transformation, the 80386 transforms a linear address into a physical address. This phase of address transformation implements the basic features needed for page-oriented virtual-memory systems and page-level protection.
The page translation step is optional. Page translation is in effect only when the PG bit of CR0 is set. This bit is typically set by the operating system during software initialization. The PG bit must be set if the operating system is to implement multiple virtual 8086 tasks, page-oriented protection, or page-oriented virtual memory.
The 80386 provides an array of protection mechanisms that operating systems can selectively employ to fit their needs. One form of protection is the separation of task address spaces by segment descriptor tables and page tables. This separation effectively prevents application tasks from interfering with each other's code and data. In addition to isolating tasks from each other, the 80386 provides facilities for protecting the operating system from application code, for protecting one part of the operating system from other parts, and for protecting a task from some of its own errors. All 80386 protection facilities are implemented on-chip.
Many of 80386 proteciton facilities are based on the notion of a privilege hierarchy. At any instant, a task's privilege is equal to the privilege level of the code segment it is executing. In each segment descriptor is a field that defines the privilege level of the associated segment. The field may take one of four values. Privilege level 0 is the most-privileged level and privilege level 3 is the least-privileged level.
FIG. 7 shows how the 80386 privilege levels can be used to establish different protection policies. An unprotected system can be implemented by simply placing all procedures in a segment (or segments) whose privilege level is 0. The traditional supervisor/user distinction can be implemented by placing user (application) code in a privilege level 3 segment and supervisor procedures in a segment whose privilege level is 0. An operating system can also use privilege levels 1 and 2, if desired. For example, the most critical and least-changing operating system procedures (sometimes called the operating system kernel) might be assigned privilege level 0. Privilege level 1 might be used for the services that are less critical and more frequently modified or extended, for example, device drivers. Level 2 might be reserved for use by original equipment manufacturers (OEM's). Such OEM's could then assign their code privilege level 2, leaving level 3 for the end users. In this way, the OEM software is protected from the end users; the operating system is protected from both the OEM and the end users; and, the operating system kernel is protected from all other software, including that part of the operating system that is subject to frequent change.
A task's privilege level determines what instructions it may execute and what subset of the segments and/or pages in its address space it may reference. The processor checks for consistency between a task's privilege level and the privilege level of the segment or page that is the target of an instruction. Any attempt by a task to use a more privileged segment or page makes the processor stop execution of the instruction and raise a general protection exception.
In addition to defining which segments and pages it can use, a task's privilege level defines the instructions it can execute. The 80386 has a number of instructions whose execution must be tightly controlled to prevent serious system disruption. All of the instructions that load new values into the system registers are examples of privileged instructions.
The descriptors in a task's Local Descriptor Table (LDT) and Global Descriptor Table (GDT) define the task's logical address space. The segments defined in these tables are theoretically addressable, because the descriptor tables provide the information necessary to compute a segment's address. However, an addressable segment may not be accessible to a particular operation because of the additional protection checks made by the 80386. The 80386 checks every segment reference (whether generated by the execution of an instruction or an instruction fetch) to verify that the reference is consistent with the protection attributes of the segment as described below.
Privilege: To access a segment, a program must be at least as privileged as the segment. For example, a program running at level 3 can only reference segments whose privilege level is also 3, while a program running at level 0 can access all segments in its logical address space.
Limit: A reference to a segment must fall within the segment's limit. Segment limits enable the processor to trap common programming errors such as stack overflow, bad pointers and array subscripts, and bad call and jump addresses. In cases where the operating system can determine that a reference outside the bounds of a segment is not an error (stack overflow is an example in some systems), the operating system can extend the segment (for example, by adding a page to it) and restart the instruction.
Type: Each descriptor contains a type field that the processor checks for consistency with the instruction it is executing. Ordinary segments have a type of code or data, enabling the processor to catch an attempt to overwrite code, for example, the segment types manipulated directly by applications are code and data. System descriptors are also typed so the processor can verify when it is switching tasks, for example, that the segment named in Jump TSS instruction is in fact a Task Stage Segment.
Rights: A segment descriptor can be marked with rights that restrict the operations permitted on the associated segment. Code segments can be marked executable or executable-and-readable. Data segments can be marked read-only or readable-and-writable.
All of the checks described above depend on the integrity of descriptors. If a task executing its application code could change a descriptor, the checks would guarantee nothing. For this reason, an operating system can restrict access to descriptor tables to privilege level 0 code.
Note that for sharing, different descriptors for the same segment (that is, aliases) may have different protection attributes, allowing, for example, one task to read and write a segment while another can only read it. Aliases also permit the operating system to override the protection system when necessary, for example, to move a code segment.
Systems that do not make extensive use of segments can instead protect pages. (Page protection can also be applied to sections of large segments.) Like a descriptor, a page table entry has a set of protection attributes; the 80386 checks every reference to the page for conformance to these attributes.
A page table entry can be marked with one of two privilege levels, user or supervisor. User level corresponds to privilege level 3 but supervisor pages can only be accessed by tasks running at privilege levels 0, 1, or 2. A user page can also be marked read-only or readable-and-writable.
The 80386 microprocessor checks the protection attributes of a page after verifying that an access is consistent with the segment attributes. Thus, page protection is a convenient way for an operating system to apply additional protection to portions of a segment. For example, an operating system can safely store task-related operating system data, such as page tables and file descriptors, in a task's data segment by making the containing pages supervisor pages.